#include "avr_sps.h"
#include "ui_avr_sps.h"

#include <QResizeEvent>
#include <QDebug>
#include <QMessageBox>
#include <QDockWidget>
#include <QListWidget>
#include <QGridLayout>
#include <QSpacerItem>
#include <QHeaderView>
#include <QFileDialog>
#include <QMessageBox>

#include "export.h"
#include "storage.h"

AVR_SPS::AVR_SPS(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::AVR_SPS)
{
    ui->setupUi(this);

	dockTree = new QDockWidget(tr("Library"), this);
	dockTree->setAllowedAreas(Qt::LeftDockWidgetArea);
	tree = new QTreeWidget(dockTree);
	tree->header()->close();
    tree->setMinimumWidth(300);
	dockTree->setWidget(tree);
	addDockWidget(Qt::LeftDockWidgetArea, dockTree);

	dockToolBar = new QDockWidget(tr("ToolBar"), this);
	dockToolBar->setAllowedAreas(Qt::RightDockWidgetArea);
	QWidget *toolBar = new QWidget(dockToolBar);
	toolBar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
	toolBar->setWindowFlags(toolBar->windowFlags() | Qt::MSWindowsFixedSizeDialogHint);
	dockToolBar->setWidget(toolBar);
	QGridLayout *toolBarGrid = new QGridLayout();

	btnWire = new QPushButton(QIcon(QApplication::applicationDirPath() + "\\Pfeil.png"), "", toolBar);
	btnWire->setCheckable(true);
	QObject::connect(btnWire, SIGNAL(clicked(bool)), this, SLOT(toolBarSelectWire(bool)));
	btnWire->resize(50, 50);
	toolBarGrid->addWidget(btnWire, 0, 0);
	btnWire->setChecked(true); // default Zustand beim Start

	btnKink = new QPushButton(QIcon(QApplication::applicationDirPath() + "\\Linie_knicken.png"), "", toolBar);
	btnKink->setCheckable(true);
	QObject::connect(btnKink, SIGNAL(clicked(bool)), this, SLOT(toolBarSelectKink(bool)));
	btnKink->resize(50, 50);
	toolBarGrid->addWidget(btnKink, 0, 1);

	QPushButton *btn = new QPushButton(toolBar);
	btn->resize(50, 50);
	toolBarGrid->addWidget(btn, 1, 0);

	btn = new QPushButton(toolBar);
	btn->resize(50, 50);
	toolBarGrid->addWidget(btn, 1, 1);

	toolBarGrid->addItem(new QSpacerItem(2, 0, QSizePolicy::Maximum, QSizePolicy::Maximum), 2, 0, Qt::AlignLeft | Qt::AlignTop);
	toolBarGrid->addItem(new QSpacerItem(2, 1, QSizePolicy::Maximum, QSizePolicy::Maximum), 2, 0, Qt::AlignRight | Qt::AlignTop);
	toolBar->setLayout(toolBarGrid);

	addDockWidget(Qt::RightDockWidgetArea, dockToolBar);

	dockProperty = new QDockWidget(tr("Properties"), this);
	dockProperty->setAllowedAreas(Qt::LeftDockWidgetArea);
	propertyGrid = new QTableView(dockProperty);
	propertyGrid->verticalHeader()->setVisible(false);
	propertyGrid->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
	propertyModel = new QStandardItemModel(0, 2);
	propertyGrid->setModel(propertyModel);
	propertyModel->setHeaderData(0, Qt::Horizontal, QObject::tr("Property"));
	propertyModel->setHeaderData(1, Qt::Horizontal, QObject::tr("Value"));

	dockProperty->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
	dockProperty->setWindowFlags(toolBar->windowFlags() | Qt::MSWindowsFixedSizeDialogHint);
	dockProperty->setWidget(propertyGrid);

	addDockWidget(Qt::LeftDockWidgetArea, dockProperty);

	sch = new SchematicBase(this);
	setCentralWidget(sch);
	QObject::connect(sch, SIGNAL(onFuncBlockSelectChanged(FuncBlockBase*)), this, SLOT(selectFuncBlockChanged(FuncBlockBase*)));

        QDir *dir = new QDir(QApplication::applicationDirPath() + "/library/");
    dir->setFilter(QDir::Dirs);

    QTreeWidgetItem *group, *component;

    QFileInfoList list = dir->entryInfoList();
    for (int i = 0; i < list.size(); i++)
    {
        QFileInfo dirInfo = list.at(i);
        if ((dirInfo.isDir()) && (dirInfo.fileName() != ".") && (dirInfo.fileName() != ".."))
        {
            group = new QTreeWidgetItem(tree);
            group->setText(0, dirInfo.fileName());
            QDir *files = new QDir(dirInfo.filePath());
            files->setFilter(QDir::Files);
            QFileInfoList fileList = files->entryInfoList();
            for (int f=0; f<fileList.size(); f++)
            {
                QFileInfo filesInfo = fileList.at(f);
                if (!filesInfo.isHidden())
                {
                    component = new QTreeWidgetItem(group);
                    component->setText(0, filesInfo.completeBaseName());
                    QString nodeData = filesInfo.absoluteFilePath();
                    QVariant data = qVariantFromValue(nodeData);
                    qVariantSetValue(data, nodeData);
                    component->setData(0, Qt::UserRole, data);
                }
            }
        }
    }
    QObject::connect(tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), sch, SLOT(addFunctionBlock(QTreeWidgetItem*,int)));

	newAct = new QAction(tr("&New"), this);
	newAct->setShortcuts(QKeySequence::New);
	newAct->setStatusTip(tr("Create a new file"));
	connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));

	openAct = new QAction(tr("&Open..."), this);
	openAct->setShortcuts(QKeySequence::Open);
	openAct->setStatusTip(tr("Open an existing file"));
	connect(openAct, SIGNAL(triggered()), this, SLOT(open()));

	saveAct = new QAction(tr("&Save"), this);
	saveAct->setShortcuts(QKeySequence::Save);
	saveAct->setStatusTip(tr("Save the document to disk"));
	connect(saveAct, SIGNAL(triggered()), this, SLOT(save()));

        exportAct = new QAction(tr("&Export Net list"), this);
        exportAct->setStatusTip(tr("Export Net list"));
        connect(exportAct, SIGNAL(triggered()), this, SLOT(export_netlist()));

	exitAct = new QAction(tr("E&xit"), this);
	exitAct->setShortcuts(QKeySequence::Quit);
	exitAct->setStatusTip(tr("Exit the application"));
	connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));

	fileMenu = menuBar()->addMenu(tr("&File"));
	fileMenu->addAction(newAct);
	fileMenu->addAction(openAct);
	fileMenu->addAction(saveAct);
        fileMenu->addAction(exportAct);
	fileMenu->addSeparator();
	fileMenu->addAction(exitAct);

	winMenu = menuBar()->addMenu(tr("Windows"));
	winMenu->addAction(dockTree->toggleViewAction());
	winMenu->addAction(dockToolBar->toggleViewAction());
        winMenu->addAction(dockProperty->toggleViewAction());

	fileToolBar = addToolBar(tr("File"));
        fileToolBar->addAction(newAct);

	statusBar()->showMessage("AVR-SPS v0.1");
        last_selected_fb = NULL;
}

AVR_SPS::~AVR_SPS()
{
    delete ui;
	delete tree;
	delete sch;
	delete dockTree;
}

 void AVR_SPS::newFile()
 {
	 QMessageBox msgBox(this);
	 msgBox.setText(tr("Invoked <b>File|New</b>"));
	 msgBox.exec();
     sch->New();
 }

 void AVR_SPS::open()
 {
     QString fileName = QFileDialog::getOpenFileName(this,
          tr("Open Schematic"), "", tr("Schematic (*.xml)"));
     sch->Open(fileName);
 }

 void AVR_SPS::save()
 {
    QString fileName = QFileDialog::getOpenFileName(this,
         tr("Save Schematic"), "", tr("Schematic (*.xml)"));
    sch->SaveAs(fileName);
 }

 void AVR_SPS::export_netlist()
 {
    ExportNetlist exp;
    try
    {
        exp.save_netlist(sch->getfbListRef(), sch->getwireListRef(), sch->getpinListRef());
    }
    catch(LoopException le)
    {
        QMessageBox mbox(this);
        mbox.setText("LoopException");
        mbox.exec();
    }
    catch(WireDriversException wde)
    {
        QMessageBox mbox(this);
        mbox.setText("WireDriversException");
        mbox.exec();
    }
 }

void AVR_SPS::resizeEvent(QResizeEvent *re)
{
	/*
	qDebug() << re->size().width() << " " << re->size().height();

	splitter->setGeometry(1,1, re->size().width(), re->size().height());
	tree->setGeometry(1,1, tree->width(), re->size().height());
	//tree->repaint();
	sch->setGeometry(sch->x(), sch->y(), re->size().width() - sch->x(), re->size().height());
	//sch->repaint();
	*/
}

void AVR_SPS::toolBarSelectWire(bool checked)
{
	if (checked)
		sch->setEditMode(emWire);
	else
		btnWire->setChecked(true); // einer muss selektiert sein

	btnKink->setChecked(false);
}

void AVR_SPS::toolBarSelectKink(bool checked)
{
	if (checked)
		sch->setEditMode(emKink);
	else
		btnKink->setChecked(true); // einer muss selektiert sein

	btnWire->setChecked(false);
}

void AVR_SPS::selectFuncBlockChanged(FuncBlockBase *fb)
{
	if (fb != NULL)
	{
		qDebug() << "FuncBlock changed " << fb->objectName();

                if (last_selected_fb != fb)
                {
                    if (last_selected_fb != NULL)
                    {
                        for (unsigned int i=0; i<last_selected_fb->getParamCount(); i++)
                        {
                            ParamBase *param = last_selected_fb->getParamRef(i);
                            QStandardItem *item = propertyModel->item(i, 1);
                            param->value = item->text();
                        }
                    }

                    propertyModel->setRowCount(fb->getParamCount()-1);
                    for (unsigned int i=0; i<fb->getParamCount(); i++)
                    {
                            ParamBase *param = fb->getParamRef(i);
                            propertyModel->setItem(i, 0, new QStandardItem(param->name));
                            propertyModel->setItem(i, 1, new QStandardItem(param->value));
                    }
                    last_selected_fb = fb;
                }
	}
	else
	{
            if (last_selected_fb != NULL)
            {
                for (unsigned int i=0; i<last_selected_fb->getParamCount(); i++)
                {
                    ParamBase *param = last_selected_fb->getParamRef(i);
                    QStandardItem *item = propertyModel->item(i, 1);
                    param->value = item->text();
                }
            }
            propertyModel->setRowCount(0);
            last_selected_fb = NULL;
	}
}
